// TestCaseModel
// (c)2007 Mark Bulmahn. mBulmahn@web.de
// License: GPL 2.0
// Project: TestCaseGenerator. http://www.codeplex.com/TestCaseGenerator

using System;
using System.Data;
using System.Collections.Generic;
using System.Text;
using DbProviderLib;
using System.IO;

namespace TestCaseModel
{
    /// <summary>
    /// The TestCaseExporter is used to export a test model's cases to
    /// external applications. It can be used for test data generation
    /// wich in turn can be used to drive UnitTests.
    /// </summary>
    public class TestCaseExporter
    {
        public enum ExportType {MSSQL = 1, SQLCE = 2, EXCEL = 3, CSV = 4, XML = 5, XMLWithHeader = 6 }

        DataTable exportData = null;

        ExportType typeOfExport;
        public ExportType TypeOfExport
        {
            get { return typeOfExport; }
            set { typeOfExport = value;}
        }

        string fileName = "";
        public string FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }

        string connectionString = "";
        public string ConnectionString
        {
            get { return connectionString; }
            set { connectionString = value; }
        }

        string destTableName = "";
        public string DestTableName
        {
            get { return destTableName; }
            set { destTableName = value; }
        }

        public bool CreateSqlCeDb(string fileName)
        {
            return SqlCeProvider.CreateSqlCeDatabase(fileName);
        }

        public void ExportData(DataTable dt)
        {
            exportData = dt;

            switch (typeOfExport)
            {
                case ExportType.SQLCE:
                    ExportSql();
                    break;
                case ExportType.MSSQL:
                    ExportSql();
                    break;
                case ExportType.EXCEL:
                    ExportExcel();
                    break;
                case ExportType.XML:
                    ExportXml(false);
                    break;
                case ExportType.XMLWithHeader:
                    ExportXml(true);
                    break;
                default:
                    throw new Exception("Not yet implemented!");
            }
        }



        /// <summary>
        /// Simple Excel Export (in fact it's a CSV-Export)
        /// </summary>
        private void ExportExcel()
        {
            List<string> expData = new List<string>();

            // export header
            string line = "";
            foreach (DataColumn dc in exportData.Columns)
            {
                line += "\"" + dc.ColumnName + "\"\t";
            }
            line = line.Substring(0, line.Length - 1);
            expData.Add(line);
            int colCnt = exportData.Columns.Count;

            // export data
            foreach (DataRow dr in exportData.Rows)
            {
                line = "";
                for (int i = 0; i < colCnt; i++)
                {
                    line += "\"" + dr[i].ToString() + "\"\t";
                }
                line = line.Substring(0, line.Length - 1);
                expData.Add(line);
            }

            // write export data
            File.WriteAllLines(FileName, expData.ToArray());
        }

        private void ExportSql()
        {
            // get a specific database provider for MSSQL or SQLCE
            IDbProvider db = null;
            switch (typeOfExport)
            {
                case ExportType.SQLCE:
                    db = DbProviderFactory.GetProvider(
                        DbProviderFactory.DbType.SQLCE, connectionString);
                    break;
                case ExportType.MSSQL:
                    db = DbProviderFactory.GetProvider(
                        DbProviderFactory.DbType.MSSQL, connectionString);
                    break;
            }

            // create the new table
            IDbCommand createTable = db.GetCommand(GetCreateTableStatement());
            try
            {
                createTable.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("already"))
                {
                    // if the table already exists it will be dropped and created
                    IDbCommand dropTable = db.GetCommand("drop table [" + destTableName + "]");
                    dropTable.ExecuteNonQuery();
                    createTable.ExecuteNonQuery();
                }
                else
                    // otherwise it must have been a different problem
                    throw ex;
            }


            // create a destination data set with a single data table connected to
            // the database
            IDbDataAdapter adapter = db.GetAdapter("select * from " + destTableName);
            DataSet ds = new DataSet();
            adapter.Fill(ds);
            DataTable destTable = ds.Tables[0];

            // fille the data table with the testcase data
            foreach (DataRow sourceRow in exportData.Rows)
            {
                DataRow newRow = destTable.NewRow();
                foreach (DataColumn dc in destTable.Columns)
                {
                    string colName = dc.ColumnName;
                    newRow[colName] = sourceRow[colName];
                }
                destTable.Rows.Add(newRow);
            }

            // write back the data to the database
            adapter.Update(ds);
        }

        private string GetCreateTableStatement()
        {
            List<string> cols = new List<string>();
            foreach (DataColumn dc in exportData.Columns)
            {
                if (((string)dc.ExtendedProperties[TestModel.COLTYPE] == TestModel.COLTYPE_PARAMETER)
                    || ((string)dc.ExtendedProperties[TestModel.COLTYPE] == TestModel.COLTYPE_ID))
                {
                    cols.Add(dc.ColumnName);
                }
            }

            string result = "create table [" + destTableName + "] (";
            foreach (string col in cols)
            {
                result += "[" + col + "] nvarchar(255),";
            }
            result = result.Substring(0, result.Length - 1);
            result += ")";

            return result;
        }

        /// <summary>
        /// Export testcases as XML data
        /// e.g. for use in VS data driven unit testing
        /// </summary>
        private void ExportXml(bool withHeader)
        {
            DataRow headerRow = exportData.NewRow();
            foreach (DataColumn col in exportData.Columns)
            {
                headerRow[col.ColumnName] = col.ColumnName;
            }
            exportData.Rows.InsertAt(headerRow, 0);
            exportData.WriteXml(fileName);
        }

    }
}
